package com.gxz.boot.condition;

import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * 响应处理工具类
 *
 * @author dengzf18
 */
public class ResponseUtil {
    private ResponseUtil() {}

    public static final String FIELD_PREFIX = ".";

    /**
     * 获取对象所有字段，包括嵌套对象
     *
     * @param recordList
     * @return
     */
    public static Map<Object, List<Field>> getObjectField(List recordList) {
        Map<Object, List<Field>> result = new HashMap<>();

        if (CollectionUtils.isEmpty(recordList)) {
            return result;
        }

        for (Object obj : recordList) {
            getObjectField(result, obj);
        }

        return result;
    }

    /**
     * 获取字段名-对象映射，嵌套字段用 . 分割，包括嵌套对象
     *
     * @return
     */
    public static Map<String, List<Object>> getFieldNameObject(List recordList) {
        Map<String, List<Object>> result = new HashMap<>();
        if (CollectionUtils.isEmpty(recordList)) {
            return result;
        }

        for (Object obj : recordList) {
            getFieldNameObject(result, "", obj);
        }

        return result;
    }

    /**
     * 收集对象所有字段名，包括嵌套对象
     *
     * @param result
     * @param record
     */
    private static void getFieldNameObject(Map<String, List<Object>> result, String parentName, Object record) {
        List<Field> fieldList = getAllFields(record);

        for (Field field : fieldList) {
            String fieldName = parentName + field.getName();
            if (result.containsKey(fieldName)) {
                List<Object> objectList = result.get(fieldName);
                objectList.add(record);
            } else {
                List<Object> objectList = new ArrayList<>();
                objectList.add(record);
                result.put(fieldName, objectList);
            }

            Object obj = null;
            try {
                // 获取字段的修饰符号码
                int typeCode = field.getModifiers();
                if (Modifier.isPublic(typeCode)) {
                    obj = field.get(record);
                } else {
                    Method method = record.getClass().getMethod("get" + getMethodName(field.getName()));
                    obj = method.invoke(record);
                }
            } catch (Exception e) {
                continue;
            }

            String fieldPrefix = fieldName + FIELD_PREFIX;

            if (obj instanceof List) {
                List list = (List)obj;
                for (Object item : list) {
                    getFieldNameObject(result, fieldPrefix, item);
                }
            }

            if (obj instanceof Set) {
                Set set = (Set)obj;
                for (Object item : set) {
                    getFieldNameObject(result, fieldPrefix, item);
                }
            }
        }
    }

    /**
     * 收集对象所有字段，包括嵌套对象
     *
     * @param map
     * @param record
     */
    private static void getObjectField(Map<Object, List<Field>> map, Object record) {
        List<Field> fieldList = getAllFields(record);
        map.put(record, fieldList);

        for (Field field : fieldList) {
            Object obj = null;
            try {
                // 获取字段的修饰符号码
                int typeCode = field.getModifiers();
                if (Modifier.isPublic(typeCode)) {
                    obj = field.get(record);
                } else {
                    Method method = record.getClass().getMethod("get" + getMethodName(field.getName()));
                    obj = method.invoke(record);
                }
            } catch (Exception e) {
                continue;
            }

            if (obj instanceof List) {
                List list = (List)obj;
                for (Object item : list) {
                    getObjectField(map, item);
                }
            }

            if (obj instanceof Set) {
                Set set = (Set)obj;
                for (Object item : set) {
                    getObjectField(map, item);
                }
            }
        }
    }

    /**
     * 获取对象所有字段，包括父类字段
     *
     * @param obj
     * @return
     */
    public static List<Field> getAllFields(Object obj) {
        List<Field> fieldList = new ArrayList<>();
        Class<?> clazz = obj.getClass();

        while (Objects.nonNull(clazz)) {
            fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
            clazz = clazz.getSuperclass();
        }

        return fieldList;
    }

    /**
     * 把字段名称第一个字母换成大写
     *
     * @param fieldName
     *            字段名称
     * @return
     * @throws Exception
     *             异常处理
     */
    private static String getMethodName(String fieldName) throws Exception {
        byte[] items = fieldName.getBytes();
        items[0] = (byte)((char)items[0] - 'a' + 'A');
        return new String(items);
    }
}
